#ifndef VERTEXS_H_
#define VERTEXS_H_

#include <GL/glut.h>
#include <vector>

class Coord;

class Vertexs {
   private:
      typedef std::pair<GLenum, size_t> Grupo;
      std::vector<Grupo> grupos;
      std::vector<float> vertexArray;

      bool estaFinalizado;

   public:
      /*
       * Representa un conjunto de Grupos de vertexs. 
       * Cada vertex esta compuesto por:
       *    2 coordenadas de textura
       *    3 coordenadas de normales
       *    3 coordenadas de posiciones
       *
       * Cada Grupo de vertexs agrupa a los vertexs que seran renderizados 
       * simultaneamente con un mismo modo.
       *
       * Ejemplo de uso, renderizado de un cuadrado y un triangulo:
       *
       *    //Primero definimos los grupos y sus vertexs.
       *    //Esto puede realizarse una sola vez.
       *    //O bien puede ser cambiado los parametros en tiempo de ejecucion
       *    Coord normal(0, 0, 1)
       *    Vertexs v;
       * 
       *    v.grupo(GL_QUADS);
       *    v.vertex(0, 0, normal, Coord(0, 0, 0));
       *    v.vertex(1, 0, normal, Coord(1, 0, 0));
       *    v.vertex(1, 1, normal, Coord(1, 1, 0));
       *    v.vertex(0, 1, normal, Coord(0, 1, 0));
       *
       *    v.grupo(GL_TRIANGLES);
       *    v.vertex(0, 0, normal, Coord(0, 0, 0));
       *    v.vertex(0, 0, normal, Coord(1, 0, 0));
       *    v.vertex(1, 1, normal, Coord(1, 1, 0));
       *
       *    v.cerrar()
       *
       *    //Renderizado
       *    v.enlazar()
       *    v.dibujar()
       *
       * */
      Vertexs();

      /*
       * Agrega un nuevo grupo de vertexs asociados al modo de renderizado pasado
       * como parametro.
       *
       * Tipicamente el uso de este metodo equivale al glBegin de OpenGL.
       * */
      void grupo(GLenum modo);

      /*
       * Vease la documentacion del constructor
       *
       * Equivale a glTexCoord, glNormal y glVertex
       * */
      void vertex(float tex_s, float tex_t, const Coord &normal, const Coord &posicion);

      /*
       * Una vez creado e inicializado la instancia Vertex, es necesario
       * cerrarla antes de dibujarla.
       * */
      void cerrar();

      /*
       * Enlaza la instancia para su posterior renderizado.
       * La instancia debe estar cerrada (vease el metodo Vertexs::cerrar)
       *
       * A diferencia de otros casos, no existe un metodo "desenlazar()"
       * */
      void enlazar() const;

      /*
       * Renderiza los Vertexs. La instancia debe estar cerrada y enlazada.
       * */
      void dibujar() const;

      /*
       * Retorna un vector de coordenadas con el formato
       *    
       *    s1 t1 nx1 ny1 nz1 x1 y1 z2 s2 t2 ....
       *
       * Donde (s t), (nx ny nz) y (x y z) son las coordenadas de textura,
       * normales y de posicion del vertice i-esimo respectivamente.
       *
       * El vector retornado es garantizado no variar hasta tanto no se modifique
       * esta instancia de Vertexs.
       *
       * Los vertices retornados pertenecen a TODOS los grupos independiente de "numGrupo".
       *
       * Los vertices que efectivamente pertenecen al grupo numero "numGrupo" comienzan
       * en la posicion del vector "pos" y continuan hasta "pos"+"cantCoords"
       * con la posicion "pos" inclusive y "pos"+"cantCoords" NO inclusive.
       *
       * Notese que la cantidad de vertices entre "pos" y "pos"+"cantCoords" es 
       * "cantCoords" / 8 pues cada vertice es definido por 8 coordenadas 
       * (2 de textura, 3 de normales y 3 de posicionamiento)
       *
       * Debe estar la instancia "cerrada".
       * */
      const std::vector<float>& data(unsigned numGrupo, unsigned &pos, unsigned &cantCoords) const;
      size_t cantGrupos() const;
};

#endif
